package com.zjj.jvm.classloader;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author zhanglei.zjj
 * @description 自定义类加载器，加载 “E:\git_workspace\project\lbw-all\jvm-stu\classPathCtz” 目录
 * @date 2023/3/4 21:31
 */
public class MyClassLoaderCtz extends ClassLoader {
    private String classPath;

    public MyClassLoaderCtz(String classPath) {
        this.classPath = classPath;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String pathName = name.replaceAll("\\.", "/");
        String detailClassName = classPath.concat("/").concat(pathName).concat(".class");
        System.out.println("detailClassName: " + detailClassName);

        byte[] bytes = null;
        try {
            FileInputStream fis = new FileInputStream(detailClassName);
            bytes = new byte[fis.available()];
            fis.read(bytes);
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return defineClass(name, bytes, 0, bytes.length);
    }

    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);

            if (c == null) {
                // If still not found, then invoke findClass in order
                // to find the class.
                long t1 = System.nanoTime();

                // 打破双亲委派机制只加载特定类，对于一些核心类如Object、String这种还是向上委托
                if (name.startsWith("com.zjj.jvm")) {
                    c = findClass(name);
                } else {
                    c = this.getParent().loadClass(name);
                }

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }

    }

    /**
     * 运行前 清理掉已经编译出来的User.class
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        MyClassLoaderCtz myClassLoaderCtz = new MyClassLoaderCtz("E:\\git_workspace\\project\\lbw-all\\jvm-stu\\classPathCtz");
        Class userClass = myClassLoaderCtz.loadClass("com.zjj.jvm.classloader.User");
        Method sayHello = userClass.getDeclaredMethod("sayHello", null);
        sayHello.invoke(userClass.newInstance(), null);

        System.out.println("类加载器为：" + userClass.newInstance().getClass().getClassLoader().getClass().getName());
        System.out.println("类加载器的父类加载器为：" + userClass.newInstance().getClass().getClassLoader().getParent().getClass().getName());
    }
}
